import logging
import random
from datetime import datetime

from pymongo import MongoClient

from .handler_interface import HandlerInterface, handler_pool
from .job_store.impl.mongo import MongoStore
from .retry_policy.impl import JobRetryIncreaseProgressively, JobRetryPolicy, OneOffJob
from .retry_policy.interface import policy_pool
from .timingwheel import Job, TimingWheel

mongo_cli = MongoClient(host='127.0.0.1', port=27017)
collection = mongo_cli.get_database('jobs').get_collection('demo')
store = MongoStore(collection)


policy_pool.init(store)


class DemoHandler01(HandlerInterface):
    logger: logging.Logger
    def __init__(self):
        self.logger = logging.getLogger("demo_svc")
        self.logger.setLevel("DEBUG")
        fmt_str = "%(asctime)s %(name)s %(levelname)s %(module)s:%(funcName)s %(message)s"
        fmt = logging.Formatter(fmt_str)
        hd = logging.StreamHandler()
        hd.setFormatter(fmt)
        hd.setLevel("DEBUG")
        self.logger.addHandler(hd)

    @classmethod
    def name(cls) -> str:
        return "demo_handler_01"

    def handle(self, **kwargs) -> bool:
        try:
            expiration = datetime.fromtimestamp(kwargs["expiration"] / 1000).strftime("%Y-%m-%d %H:%M:%S.%f")
            self.logger.info(f'过期时间: {expiration}, expiration: {kwargs["expiration"]}')
        except Exception as err:
            print(err)

    def init(self):
        pass


handler_pool.register(DemoHandler01)

timingwheel = TimingWheel(
    first_wheel_tick_ms=1000,
    wheel_size=60,
    max_workers=30,
    job_store=store
)


def add_timers(count: int, policy: JobRetryPolicy):
    now = timingwheel.current_timestamp()
    for job_id in range(count):
        expiration = now + (random.randint(5, 10)) * 1000
        timer = Job(
            job_id=f'{DemoHandler01.name()}_{policy.name()}_{job_id+1}',
            retry_policy_name=policy.name(),
            expiration=expiration,
            handler_name=DemoHandler01.name(),
            func_kwargs={"expiration": expiration},
        )
        timingwheel.new_job(timer)


add_timers(10, OneOffJob)
add_timers(10, JobRetryIncreaseProgressively)

timingwheel.join()